package com.ruoyi.iot.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.mongoplus.conditions.query.LambdaQueryChainWrapper;
import com.ruoyi.common.mongo.domain.Record;
import com.ruoyi.common.mongo.service.IRecordService;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.iot.domain.mqtt.MqttMessage;
import com.ruoyi.iot.domain.mqtt.WillMqttMessage;
import com.ruoyi.iot.domain.mqtt.constants.DeviceMqttMethod;
import com.ruoyi.iot.service.IYFHandleMqttMessageService;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.iot.mqtt.spring.client.MqttClientTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

/**
 * mqtt 处理业务层 impl
 *
 * @Author: 陈江灿
 * @CreateTime: 2025-02-14
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class IYFHandleMqttMessageServiceImpl implements IYFHandleMqttMessageService {

    @Autowired
    private MqttClientTemplate client;

    @Autowired
    private IRecordService recordService;


    /**
     * 处理mqtt消息
     * @param mqttMessage mqtt 实体参数
     * @param topic       订阅的主题
     */
    @Override
    public void handle(MqttMessage mqttMessage, String topic) {
        String method = mqttMessage.getMethod();
        log.info("mqtt收到回复:{}", method);
        switch (method) {
            case DeviceMqttMethod.ON_LINE:
                // 处理设备上线回复
                break;
            case DeviceMqttMethod.GETDEVICECONFIG_ACK:
                // 获取配置信息回复
                break;
            case DeviceMqttMethod.SETDEVICECONFIG_ACK:
                // 设置配置信息回复
                break;
            case DeviceMqttMethod.REBOOT_ACK:
                // 设备重启回复
                break;
            case DeviceMqttMethod.DEVICERESET_ACK:
                // 设备重置回复
                break;
            case DeviceMqttMethod.OPENDOORCONTROL_ACK:
                // 远程控制输出（开门和关门）回复
                break;
            case DeviceMqttMethod.PERSONCREATE_ACK:
                // 人员注册回复
                break;
            case DeviceMqttMethod.PERSONDELETE_ACK:
                // 人员删除回复
                break;
            case DeviceMqttMethod.PERSONUPDATE_ACK:
                // 人员更新回复
                break;
            case DeviceMqttMethod.PERSONFINDBYPAGE_ACK:
                // 人员分页查询回复
                break;
            case DeviceMqttMethod.SETPERSONPASSTIME_ACK:
                // 人员时间段权限设置回复
                break;
            case DeviceMqttMethod.DELETEPERSONPASSTIME_ACK:
                // 人员时间段权限删除回复
                break;
            case DeviceMqttMethod.SETPERMISSIONTIME_ACK:
                // 人员有效期设置回复
                break;
            case DeviceMqttMethod.DELETEPERMISSIONTIME_ACK:
                // 人员有效期批量删除回复
                break;
            case DeviceMqttMethod.FACECREATE_ACK:
                // 人员照片注册回复
                break;
            case DeviceMqttMethod.FACEDELETE_ACK:
                // 照片删除回复
                break;
            case DeviceMqttMethod.FACEUPDATE_ACK:
                // 照片更新回复
                break;
            case DeviceMqttMethod.UPLOADRECORD:
                // 识别记录上传
                uploadRecord(mqttMessage, topic);
                break;
            case DeviceMqttMethod.FINDRECORDS_ACK:
                // 识别记录查询回复
                break;
            case DeviceMqttMethod.DELETERECORDS_ACK:
                // 识别记录删除回复
                break;
            case DeviceMqttMethod.DELETERECORDSBYUNIXTIMEACK:
                // 识别记录删除(通过 Unix 毫秒级时间戳删除)回复
                break;
            case DeviceMqttMethod.SETADVERT_ACK:
                // 设备端广告图片设置(当前仅支持静态图片)回复
                break;
            default:
                log.error("未找到对应的方法");
                break;
        }
    }

    /**
     * 识别记录上传
     * @param mqttMessage
     * @param topic
     */
    public void uploadRecord(MqttMessage mqttMessage, String topic) {
        String key = "mqtt:device:uploadRecord:" + mqttMessage.getMsgId();
        // 可以集成redisson实现redis分布式锁,线程更加安全；下个版本再说；key先留着
        log.info("识别记录上传回复:{},主题是:{}", mqttMessage, topic);
        Object data = mqttMessage.getData();
        JSONObject jsonObject = JSONUtil.parseObj(data);
        Record record = BeanUtil.toBean(jsonObject.get("record"), Record.class);
        LambdaQueryChainWrapper<Record> lwq = recordService.lambdaQuery();
        lwq.eq(StringUtils.isNoneBlank(record.getSn()), Record::getSn, record.getSn());
        lwq.eq(StringUtils.isNoneBlank(record.getPersonId()), Record::getPersonId, record.getPersonId());
        lwq.eq(StringUtils.isNoneBlank(record.getCardId()), Record::getCardId, record.getCardId());
        lwq.eq(ObjectUtil.isNotNull(record.getCreatedAt()), Record::getCreatedAt, record.getCreatedAt());
        List<Record> list = recordService.list(lwq);
        if (list.size() > 0) {
            return;
        }
        long faceId = IdUtil.getSnowflake().nextId();
        record.setRecordId(String.valueOf(faceId));
        Boolean save = recordService.save(record);
        if (save) {
            MqttMessage message = new MqttMessage();
            message.setMethod(DeviceMqttMethod.uploadRecord_ACK);
            message.setTimestamp(System.currentTimeMillis());
            message.setMsgId(UUID.randomUUID().toString());
            HashMap<String, String> map = new HashMap<>(16);
            map.put("recordId", String.valueOf(faceId));
            message.setData(map);
            message.setSuccess(true);
            message.setCode("LAN_SUS-0");
            client.publish("device/Uface/" + record.getSn() + "/Downstream", com.alibaba.fastjson2.JSONObject.toJSONString(message).getBytes(StandardCharsets.UTF_8));
        }
    }

    /**
     * 遗嘱消息处理
     * @param message 遗嘱消息实体参数
     * @param topic   订阅的主题
     */
    @Override
    public void handleWill(WillMqttMessage message, String topic) {
        // 通知用户设备离线。暂时不做下个版本再说
        log.info("遗嘱消息:{},主题是:{}", message, topic);
    }
}
